package grpc

import (
	"context"
	"fmt"
	"time"

	"gitee.com/zawei/yggdrasil/pkg/config"
	"gitee.com/zawei/yggdrasil/pkg/log"
	"gitee.com/zawei/yggdrasil/pkg/registry"
	"gitee.com/zawei/yggdrasil/pkg/transport/client/grpc/resolver"
	_ "gitee.com/zawei/yggdrasil/pkg/transport/client/grpc/resolver"
	"google.golang.org/grpc"
)

func NewClient(name string, registry registry.Registry, opts ...grpc.DialOption) *grpc.ClientConn {
	return getConfig(name).WithRegistry(registry).WithDialOption(opts...).Build()
}

func getConfig(name string) *Config {
	c := &Config{}
	key := fmt.Sprintf("%s.%s", "client.grpc", name)
	if err := config.Get(key).Scan(c); err != nil {
		log.Fatalf("fault to scan config[%s], errors: %s", key, err.Error())
	}
	if c.Name == "" {
		c.Name = name
	}
	return c
}

func newGRPCClient(config *Config) *grpc.ClientConn {
	var ctx = context.Background()
	var dialOptions = config.dialOptions

	// 默认配置使用block
	if config.Block {
		if config.DialTimeout > time.Duration(0) {
			var cancel context.CancelFunc
			ctx, cancel = context.WithTimeout(ctx, config.DialTimeout)
			defer cancel()
		}

		dialOptions = append(dialOptions, grpc.WithBlock())
	}

	if config.KeepAlive != nil {
		dialOptions = append(dialOptions, grpc.WithKeepaliveParams(*config.KeepAlive))
	}
	if config.registry != nil {
		resolver.Register(config.registry)
	}
	if config.BalancerName != "" {
		dialOptions = append(dialOptions,
			grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingPolicy":"%s"}`, config.BalancerName)),
		)
	}
	cc, err := grpc.DialContext(ctx, config.Target, dialOptions...)
	if err != nil {
		if config.OnDialError == "panic" {
			log.Fatalf("dial grpc client: %s", err.Error())
		} else {
			log.Errorf("dial grpc client: %s", err.Error())
		}
	}
	return cc
}
